package Reeks5.VanRansbeeck.Kevin.Model;

import Reeks5.VanRansbeeck.Kevin.Model.States.Game.BlindState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Game.FlopState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Game.PokerSpelState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Game.RiverState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Game.TurnState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Player.AllinState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Player.BetState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Player.CallState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Player.CheckState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Player.FoldState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Player.NewState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Player.PokerSpelerState;
import Reeks5.VanRansbeeck.Kevin.Model.States.Player.RaiseState;
import java.util.ArrayList;

public class PokerSpeler extends Speler {
    public PokerSpeler(Spel pokerspel) {
        this("Anoniem", pokerspel);
    }
    public PokerSpeler(String naam, Spel pokerspel) {
        super(naam, pokerspel);
        this.holekaarten = new ArrayList<Kaart>(2); // in regular Poker; speler heeft maar 2 kaarten in hand
    }

    @Override
    public void call(int value) {
        if(value < this.getSaldo()) {
            stateContext.call(value);
            this.setChanged();
            this.notifyObservers();
        } else if(value >= this.getSaldo()) {
            stateContext.allin(this.getSaldo());
            this.setChanged();
            this.notifyObservers();
        }
    }
    
    public void allin() {
        stateContext.allin(this.getSaldo());
        this.setChanged();
        this.notifyObservers();
    }
    
    public void bet(int value) {
        if(value < this.getSaldo()) {
            stateContext.bet(value);
            this.setChanged();
            this.notifyObservers();
        } else if(value == this.getSaldo()) {
            stateContext.allin(this.getSaldo());
            this.setChanged();
            this.notifyObservers();
        }
    }
    
    public void check() {
        stateContext.check();
        this.setChanged();
        this.notifyObservers();
    }
    
    public void raise(int value) {
        if(value < this.getSaldo()) {
            stateContext.raise(value);
            this.setChanged();
            this.notifyObservers();
        } else if(value >= this.getSaldo()) {
            stateContext.allin(this.getSaldo());
            this.setChanged();
            this.notifyObservers();
        }
    }

    public void allin(int value) {
        stateContext.allin(this.getSaldo());
        this.setChanged();
        this.notifyObservers();
    }
    
    public boolean canCheck() {
        boolean ok = false;
        PokerSpelerState state = stateContext.getStatus();
        PokerSpelState spelState = getSpel().getSpelContext().getSpelState();
        PokerSpel ps = (PokerSpel)spel;
        /*
         * Een speler kan checken indien:
         * - Hij in newState zit
         * - EN voor hem nog niemand in betState OF raiseState OF callState OF AllinState zit
         * - EN spelState in preflopState OF flopState OF turnState OF riverState zit
         */
        
        if(state instanceof NewState) {
            if(!ps.hasBet() && !ps.hasRaised()) {
                if(spelState instanceof BlindState || spelState instanceof FlopState || spelState instanceof TurnState || spelState instanceof RiverState) {
                    ok = true;
                }
            }
        }
        
        return ok;
    }
    
    public boolean canAllin() {
        boolean ok = false;
        PokerSpelerState state = stateContext.getStatus();
        PokerSpelState spelState = getSpel().getSpelContext().getSpelState();
        PokerSpel ps = (PokerSpel)spel;
        /*
         * Een speler kan All-In indien:
         * - Hij in newState OF betState OF raiseState zit
         * - EN voor hem nog iemand in betState OF raiseState OF AllinState zit
         * - EN spelState in preflopState OF flopState OF turnState OF riverState zit
         */
        
        if(state instanceof NewState || state instanceof BetState || state instanceof RaiseState) {
            if(ps.hasBet() || ps.hasRaised()) {
                if(spelState instanceof BlindState || spelState instanceof FlopState || spelState instanceof TurnState || spelState instanceof RiverState) {
                    ok = true;
                }
            }
        }
        
        return ok;
    }
    
    
    public boolean canBet() {
        boolean ok = false;
        PokerSpelerState state = stateContext.getStatus();
        PokerSpelState spelState = getSpel().getSpelContext().getSpelState();
        PokerSpel ps = (PokerSpel)spel;
        /*
         * Een speler kan betten indien:
         * - Hij in newState zit
         * - EN voor hem nog niemand in betState OF raiseState zit
         * - EN spelState in preflopState OF flopState OF turnState OF riverState zit
         * 
         * -- TODO: kan betten indien hij nog genoeg geld heeft voor een bet!
         */
        
        if(state instanceof NewState) {
            if(!ps.hasBet() && !ps.hasRaised()) {
                if(spelState instanceof BlindState || spelState instanceof FlopState || spelState instanceof TurnState || spelState instanceof RiverState) {
                    ok = true;
                }
            }
        }
        
        return ok;
    }
    
    
    public boolean canRaise() {
        boolean ok = false;
        PokerSpelerState state = stateContext.getStatus();
        PokerSpelState spelState = getSpel().getSpelContext().getSpelState();
        PokerSpel ps = (PokerSpel)spel;
        /*
         * Een speler kan raisen indien:
         * - Hij in newState OF checkState zit
         * - EN voor hem al iemand in betState OF raiseState zit
         * - EN spelState in preflopState OF flopState OF turnState OF riverState zit
         * 
         * -- TODO: kan raisen indien hij nog genoeg geld heeft voor een raise!
         */
        
        if(state instanceof NewState || state instanceof CheckState) {
            if(ps.hasBet() || ps.hasRaised()) {
                if(spelState instanceof BlindState || spelState instanceof FlopState || spelState instanceof TurnState || spelState instanceof RiverState) {
                    ok = true;
                }
            }
        }
        
        return ok;
    }
    
    public boolean canFold() {
        boolean ok = false;
        /*
         * Een speler kan folden indien:
         * - Hij niet in foldState of AllinState zit
         * - Het spel in flop/turn/river zit
         */
        PokerSpelerState state = stateContext.getStatus();
        PokerSpelState spelState = getSpel().getSpelContext().getSpelState();
        PokerSpel ps = (PokerSpel)spel;
        
        if(!(state instanceof FoldState || state instanceof AllinState)) {
            if(spelState instanceof BlindState || spelState instanceof FlopState || spelState instanceof TurnState || spelState instanceof RiverState) {
                ok = true;
            }
        }
        return ok;
    }
    
    public boolean canCall() {
        boolean ok = false;
        /*
         * Een speler kan callen indien:
         * - Hij niet in callState OF foldState OF AllinState zit
         * - Er na hem nog iemand (meer) gebet OF geraised heeft
         * - Het spel in flop/turn/river zit
         * 
         * -- TODO: kan callen indien hij genoeg geld in saldo heeft!
         */
        PokerSpelerState state = stateContext.getStatus();
        PokerSpelState spelState = getSpel().getSpelContext().getSpelState();
        PokerSpel ps = (PokerSpel)spel;
        
        if(!(state instanceof FoldState || state instanceof AllinState || state instanceof CallState)) {
            if(ps.hasBet() || ps.hasRaised()) {
                if(spelState instanceof BlindState || spelState instanceof FlopState || spelState instanceof TurnState || spelState instanceof RiverState) {
                    ok = true;
                }
            }
        }
        return ok;
    }
    
}
